如何正确关闭 tcp 连接?

您所在的位置:网站首页 socket c语言 如何正确关闭 tcp 连接?

如何正确关闭 tcp 连接?

2023-04-13 16:05| 来源: 网络整理| 查看: 265

shutdown(both)还需要close,不然你就泄漏了一个或几个handle或fd以及相关资源。

read返回0表示你收到了对方发来的fin,这可能是对方调用shutdown(send),也可能是对方调用了close()。从tcp协议本身来说,你是无法知道对方到底是调用了close()还是调用了shutdown(send)的,os的tcp协议栈也不知道。因此此时是否要close取决于你的应用。通常来说如果对方调用的是close,那么你也可以close。否则你不能close,例如对方发送一个包给你并shutdown write然后调用recv,这时候你还可以返回一个或多个包,连接此时处于半关闭状态,可以一直持续。这么做的客户端不多(connect, send, shtudown(send), recv();),但的确有,而且是完全合法的。如果通讯双方都是你自己的代码,那么你知道是哪种情况。如果你不能了解对方的代码,甚至你是个proxy,两边代码你都不了解,那么通常来说你不能close。

很多server/proxy的实现为当read返回0就close,这种实现是错误的,这个实现无法兼容刚才我说的那种情况。对于proxy来说,正确的做法是透传双方的行为。因此,当你read(client_side_socket)返回0时,你应该对另外一端调用shutdown(server_side_socket, send),这样服务器就会read返回0,你透明的传递了这个行为。那么作为proxy,你什么时候才能close呢?client_socket和server_socket上read都返回了0,或者有任何一方返回了-1时你可以close。当然你也可以考虑设置一个超时时间,如果线路上超过5分钟没有数据你就断开,但这是另一个维度的问题。

关于close,要注意的是默认情况下它是一个异步的过程。作为proxy来说,如果你想避免大量close_wait,那么你可以在close之前shutdown,然后启动一个5s的delaytask,在delaytask里设置超时时间为0的so_linger,然后close,对socket进行hard close。这时候close是同步的,如果此时不能优雅关闭,那么系统会立刻强制关闭。

我没有看muduo的代码。如果你在2处close同一个socket,这是高危行为。因为2次close之间很可能会有一个新socket产生并且值和你第一次close的那个一样。你第二次close就会错误的close了一个不属于你的socket。这种错误非常难查,因此绝对不要干这种事。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3